using Sage.Http.Models;
using System.Collections;
using System.Globalization;
using System.Text;

namespace Sage.Http.Utils
{
    /// <summary>
    /// 字典转换工具类，提供字典到各种格式的转换功能
    /// </summary>
    public static class DictionaryConverter
    {
        /// <summary>
        /// 将字典转换为指定格式的字符串
        /// </summary>
        /// <param name="data">字典数据</param>
        /// <param name="bodyType">目标格式类型</param>
        /// <returns>转换后的字符串</returns>
        /// <exception cref="ArgumentNullException">当 data 为 null 时抛出</exception>
        /// <exception cref="NotSupportedException">当 bodyType 不支持时抛出</exception>
        public static string ConvertToString(IDictionary<string, object> data, BodyType bodyType)
        {
            ArgumentNullException.ThrowIfNull(data);

            return bodyType switch
            {
                BodyType.Json => ConvertToJson(data),
                BodyType.Form => ConvertToFormData(data),
                BodyType.Xml => ConvertToXml(data),
                BodyType.Text => ConvertToText(data),
                _ => throw new NotSupportedException($"不支持的 BodyType: {bodyType}")
            };
        }

        /// <summary>
        /// 将字典转换为JSON字符串（AOT 兼容）
        /// </summary>
        /// <param name="data">字典数据</param>
        /// <returns>JSON字符串</returns>
        public static string ConvertToJson(IDictionary<string, object> data)
        {
            if (data == null)
                return "null";

            var json = new StringBuilder();
            json.Append('{');

            bool first = true;
            foreach (var kvp in data)
            {
                if (!first)
                    json.Append(',');

                // 转义键名
                json.Append('"');
                json.Append(EscapeJsonString(kvp.Key));
                json.Append("\":");

                // 处理值
                json.Append(ConvertValueToJson(kvp.Value));

                first = false;
            }

            json.Append('}');
            return json.ToString();
        }

        /// <summary>
        /// 将字典转换为表单数据字符串
        /// </summary>
        /// <param name="data">字典数据</param>
        /// <returns>表单数据字符串</returns>
        public static string ConvertToFormData(IDictionary<string, object> data)
        {
            if (data == null)
                return string.Empty;

            var formData = new List<string>();
            foreach (var kvp in data)
            {
                var key = Uri.EscapeDataString(kvp.Key);
                var value = Uri.EscapeDataString(kvp.Value?.ToString() ?? string.Empty);
                formData.Add($"{key}={value}");
            }
            return string.Join("&", formData);
        }

        /// <summary>
        /// 将字典转换为XML字符串
        /// </summary>
        /// <param name="data">字典数据</param>
        /// <returns>XML字符串</returns>
        public static string ConvertToXml(IDictionary<string, object> data)
        {
            if (data == null)
                return "<?xml version=\"1.0\" encoding=\"utf-8\"?><root></root>";

            var xml = new StringBuilder();
            xml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            xml.AppendLine("<root>");

            foreach (var kvp in data)
            {
                var key = System.Security.SecurityElement.Escape(kvp.Key);
                var value = System.Security.SecurityElement.Escape(kvp.Value?.ToString() ?? string.Empty);
                xml.AppendLine($"  <{key}>{value}</{key}>");
            }

            xml.AppendLine("</root>");
            return xml.ToString();
        }

        /// <summary>
        /// 将字典转换为纯文本字符串
        /// </summary>
        /// <param name="data">字典数据</param>
        /// <returns>纯文本字符串</returns>
        public static string ConvertToText(IDictionary<string, object> data)
        {
            if (data == null)
                return string.Empty;

            var text = new StringBuilder();
            foreach (var kvp in data)
            {
                if (text.Length > 0)
                    text.AppendLine();
                text.Append($"{kvp.Key}: {kvp.Value}");
            }
            return text.ToString();
        }

        #region JSON 转换辅助方法

        /// <summary>
        /// 将值转换为 JSON 格式（AOT 兼容）
        /// </summary>
        /// <param name="value">要转换的值</param>
        /// <returns>JSON 格式的字符串</returns>
        private static string ConvertValueToJson(object? value)
        {
            return value switch
            {
                null => "null",
                string str => $"\"{EscapeJsonString(str)}\"",
                bool b => b ? "true" : "false",
                int i => i.ToString(CultureInfo.InvariantCulture),
                long l => l.ToString(CultureInfo.InvariantCulture),
                float f => f.ToString("G", CultureInfo.InvariantCulture),
                double d => d.ToString("G", CultureInfo.InvariantCulture),
                decimal dec => dec.ToString(CultureInfo.InvariantCulture),
                DateTime dt => $"\"{dt:yyyy-MM-ddTHH:mm:ss.fffZ}\"",
                IDictionary<string, object> dict => ConvertToJson(dict),
                IEnumerable enumerable => ConvertArrayToJson(enumerable),
                _ => $"\"{EscapeJsonString(value.ToString() ?? string.Empty)}\""
            };
        }

        /// <summary>
        /// 将数组转换为 JSON 格式（AOT 兼容）
        /// </summary>
        /// <param name="enumerable">可枚举对象</param>
        /// <returns>JSON 数组字符串</returns>
        private static string ConvertArrayToJson(IEnumerable enumerable)
        {
            var json = new StringBuilder();
            json.Append('[');

            bool first = true;
            foreach (var item in enumerable)
            {
                if (!first)
                    json.Append(',');

                json.Append(ConvertValueToJson(item));
                first = false;
            }

            json.Append(']');
            return json.ToString();
        }

        /// <summary>
        /// 转义 JSON 字符串中的特殊字符（AOT 兼容）
        /// </summary>
        /// <param name="str">要转义的字符串</param>
        /// <returns>转义后的字符串</returns>
        private static string EscapeJsonString(string str)
        {
            if (string.IsNullOrEmpty(str))
                return string.Empty;

            var escaped = new StringBuilder(str.Length);

            foreach (char c in str)
            {
                switch (c)
                {
                    case '"':
                        escaped.Append("\\\"");
                        break;
                    case '\\':
                        escaped.Append("\\\\");
                        break;
                    case '\b':
                        escaped.Append("\\b");
                        break;
                    case '\f':
                        escaped.Append("\\f");
                        break;
                    case '\n':
                        escaped.Append("\\n");
                        break;
                    case '\r':
                        escaped.Append("\\r");
                        break;
                    case '\t':
                        escaped.Append("\\t");
                        break;
                    default:
                        if (c < ' ')
                        {
                            escaped.Append($"\\u{(int)c:x4}");
                        }
                        else
                        {
                            escaped.Append(c);
                        }
                        break;
                }
            }

            return escaped.ToString();
        }

        #endregion
    }
}